Skip to content

Releasing v4.11.0#107

Merged
cb-alish merged 3 commits into
v4from
release-v4.11.0
Jun 29, 2026
Merged

Releasing v4.11.0#107
cb-alish merged 3 commits into
v4from
release-v4.11.0

Conversation

@cb-alish

@cb-alish cb-alish commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

v4.11.0 (2026-06-23)


Bug Fixes:

  • Fixed JSON request body serialization where Timestamp parameters were sent in a human-readable format (e.g. "expires_at":"2026-06-23 09:54:44.513") instead of Unix seconds. They are now serialized as numeric Unix seconds (e.g. "expires_at":1782189229), matching the form-url-encoded path and the format expected by the API. This affects all JSON content-type endpoints, such as create_promotional_grant in PromotionalGrant.

Released v4.11.0 with a JSON request-body serialization fix: Timestamp fields in application/json now serialize as numeric Unix seconds (not human-readable strings). Regenerated parameter classes add toJsonMap() to preserve nested JSON structures (fixing flattening/double-encoding). Updated PromotionalGrant and UsageEvent (usage_timestamp now Long), plus new tests and changelog.

@snyk-io

snyk-io Bot commented Jun 23, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The PR updates JSON serialization for Timestamp, Date, and enum values, adds regression tests for nested serialization and PromotionalGrantsParams JSON/form-body output, updates multiple request params to emit nested JSON, and bumps release metadata to 4.11.0.

Changes

JSON serialization and release metadata

Layer / File(s) Summary
JSON serializer rewrite
src/main/java/com/chargebee/v4/internal/JsonUtil.java
JsonUtil now uses a configured Gson instance with custom Timestamp, Date, and Enum serializers, and toJson(Map) / toJson(List) delegate directly to Gson.
JsonUtil regression tests
src/test/java/com/chargebee/v4/internal/JsonUtilTest.java
JsonUtilTest adds coverage for Timestamp, Date, and Enum serialization, plus recursive handling of nested maps, lists, arrays, and primitive JSON values.
Model JSON serialization updates
src/main/java/com/chargebee/v4/models/entitlement/..., src/main/java/com/chargebee/v4/models/ledgerOperation/..., src/main/java/com/chargebee/v4/models/offerEvent/..., src/main/java/com/chargebee/v4/models/offerFulfillment/..., src/main/java/com/chargebee/v4/models/personalizedOffer/..., src/main/java/com/chargebee/v4/models/promotionalGrant/..., src/main/java/com/chargebee/v4/models/ramp/..., src/main/java/com/chargebee/v4/models/usageEvent/...
Multiple request params now build nested JSON maps for toJsonString(), selected enums are swapped, and usage event batch ingest changes usageTimestamp to Long.
PromotionalGrants serialization tests
src/test/java/com/chargebee/v4/models/promotionalGrant/params/PromotionalGrantsParamsJsonTest.java
PromotionalGrantsParamsJsonTest adds JSON and form-body checks for expires_at, metadata, request content types, and form-body parsing.
Release version bump
CHANGELOG.md, VERSION, build.gradle.kts
Release notes, version file, and Gradle version are updated from 4.10.0 to 4.11.0.

Sequence Diagram(s)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes


Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/java/com/chargebee/v4/internal/JsonUtil.java`:
- Around line 40-41: The Timestamp serializer in JsonUtil is still emitting
epoch milliseconds via the registered TypeAdapter, but the contract now expects
Unix seconds. Update the Timestamp serialization used by the Gson builder in
JsonUtil so it converts the value from src.getTime() to seconds before creating
the JsonPrimitive, and make sure the behavior matches getTimestamp(...) and the
regression tests for expires_at.
- Around line 45-46: The enum JSON serializer in JsonUtil currently lowercases
names using the JVM default locale, which can change wire-format values on
locale-sensitive systems. Update the serializer registered in JsonUtil’s type
hierarchy adapter to use Locale.ROOT when calling toLowerCase so enum
serialization stays stable regardless of default locale.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3acd0fdb-16e5-4475-a148-af91e86b79a0

📥 Commits

Reviewing files that changed from the base of the PR and between 2b88019 and 0ef3c51.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • VERSION
  • build.gradle.kts
  • src/main/java/com/chargebee/v4/internal/JsonUtil.java
  • src/test/java/com/chargebee/v4/internal/JsonUtilTest.java
  • src/test/java/com/chargebee/v4/models/promotionalGrant/params/PromotionalGrantsParamsJsonTest.java

Comment thread src/main/java/com/chargebee/v4/internal/JsonUtil.java
Comment thread src/main/java/com/chargebee/v4/internal/JsonUtil.java
Replace the hand-rolled `instanceof`-chain inside `toJsonElement(...)` with
a single static `Gson` instance configured via `GsonBuilder`:

  - `Timestamp` → Unix-seconds JSON number (`JsonSerializer<Timestamp>`)
  - `Date`      → `yyyy-MM-dd` JSON string  (`JsonSerializer<Date>`)
  - `Enum`      → lowercase `name()` string (`registerTypeHierarchyAdapter`)

`toJson(Map)` and `toJson(List)` now delegate to `GSON.toJson(...)`; Gson
natively walks nested maps, lists, and `Object[]` and dispatches each
value through the registered adapters via its `ObjectTypeAdapter`. The
builder also calls `disableHtmlEscaping()` and `serializeNulls()` to
preserve the prior behavior (`JsonElement.toString()` semantics and the
explicit `"key":null` shape).

No behavior change for the Chargebee API contract; the full JsonUtil and
PromotionalGrantsParams regression suites pass.

Co-authored-by: Cursor <cursoragent@cursor.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
src/main/java/com/chargebee/v4/internal/JsonUtil.java (2)

40-41: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Existing blocker still applies: serialize Timestamp as Unix seconds.

Line 41 emits epoch milliseconds, while the PR objective and the local comment require Unix seconds. This keeps JSON expires_at values 1000x too large; update this serializer and the new millisecond-based test expectations.

Proposed fix
 .registerTypeAdapter(Timestamp.class,
-        (JsonSerializer<Timestamp>) (src, t, c) -> new JsonPrimitive(src.getTime()))
+        (JsonSerializer<Timestamp>) (src, t, c) -> new JsonPrimitive(src.getTime() / 1000L))

As per path instructions, this is limited to a merge-blocking correctness issue.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/chargebee/v4/internal/JsonUtil.java` around lines 40 - 41,
The Timestamp serializer in JsonUtil currently emits epoch milliseconds via the
JsonSerializer registered in JsonUtil, which breaks the expected Unix-seconds
format. Update the Timestamp type adapter to divide the timestamp value by 1000
before serializing, and adjust the related tests that currently assert
millisecond-based expires_at values so they expect Unix seconds instead.

Source: Path instructions


45-46: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Existing blocker still applies: make enum casing locale-independent.

src.name().toLowerCase() uses the JVM default locale, so API enum values can change on Turkish/default-locale systems. Use Locale.ROOT.

Proposed fix
 .registerTypeHierarchyAdapter(Enum.class,
-        (JsonSerializer<Enum<?>>) (src, t, c) -> new JsonPrimitive(src.name().toLowerCase()))
+        (JsonSerializer<Enum<?>>) (src, t, c) -> new JsonPrimitive(src.name().toLowerCase(java.util.Locale.ROOT)))

As per path instructions, this is limited to a merge-blocking correctness issue.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/chargebee/v4/internal/JsonUtil.java` around lines 45 - 46,
The enum serialization in JsonUtil’s type hierarchy adapter still depends on the
JVM default locale, so update the Enum.class serializer to convert names to
lowercase using Locale.ROOT instead of the locale-sensitive default. Keep the
change local to the existing JsonUtil registration logic so the JSON output from
enum values remains stable across all locales.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@src/main/java/com/chargebee/v4/internal/JsonUtil.java`:
- Around line 40-41: The Timestamp serializer in JsonUtil currently emits epoch
milliseconds via the JsonSerializer registered in JsonUtil, which breaks the
expected Unix-seconds format. Update the Timestamp type adapter to divide the
timestamp value by 1000 before serializing, and adjust the related tests that
currently assert millisecond-based expires_at values so they expect Unix seconds
instead.
- Around line 45-46: The enum serialization in JsonUtil’s type hierarchy adapter
still depends on the JVM default locale, so update the Enum.class serializer to
convert names to lowercase using Locale.ROOT instead of the locale-sensitive
default. Keep the change local to the existing JsonUtil registration logic so
the JSON output from enum values remains stable across all locales.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5b23ee97-b5db-45de-9ac1-13a735e52354

📥 Commits

Reviewing files that changed from the base of the PR and between 0ef3c51 and e8fe429.

📒 Files selected for processing (3)
  • src/main/java/com/chargebee/v4/internal/JsonUtil.java
  • src/test/java/com/chargebee/v4/internal/JsonUtilTest.java
  • src/test/java/com/chargebee/v4/models/promotionalGrant/params/PromotionalGrantsParamsJsonTest.java

- Regenerate param classes with dedicated toJsonMap()/toJsonString() so
  JSON content-type endpoints emit a proper nested structure instead of
  reusing the form-url-encoded flattening (e.g. events[...][]) and
  double-encoding nested objects.
- Change usage_timestamp on UsageEvent create and batch ingest from
  Timestamp to Long (epoch milliseconds) to preserve the precision the
  ingestion API requires.
- Update PromotionalGrantsParamsJsonTest to assert the nested-object JSON
  body for metadata.
- Update CHANGELOG for v4.11.0 (release date and new bug-fix entries).

Co-authored-by: Cursor <cursoragent@cursor.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/main/java/com/chargebee/v4/models/entitlement/params/EntitlementListParams.java (1)

160-225: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Do not swap these public enum type names in a 4.11.0 release.

Changing EntityTypeIs/EntityTypeIn removes old nested enum symbols from the published API. Existing consumers compiled against either type will break even though the wire values are unchanged. The same compatibility break also appears in src/main/java/com/chargebee/v4/models/ramp/params/RampListParams.java.

Keep the old enum names, or defer the rename to a major release with compatibility shims. As per path instructions, "Comment only when the issue must be resolved before merge."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/chargebee/v4/models/entitlement/params/EntitlementListParams.java`
around lines 160 - 225, The public nested enum names in EntityTypeIn and
EntityTypeIs have been swapped, which breaks the existing API surface for
consumers compiled against the old symbols. Restore the original enum type names
in EntitlementListParams and keep the wire values unchanged; if the rename is
still needed, add backward-compatible aliases/shims instead of removing the old
nested types. Apply the same compatibility fix in RampListParams so both
parameter classes preserve their published enum symbols for this release.

Source: Path instructions

src/test/java/com/chargebee/v4/models/promotionalGrant/params/PromotionalGrantsParamsJsonTest.java (1)

36-57: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Fix JSON timestamp expectations to Unix seconds.

The PR objective says JSON Timestamp params must serialize as numeric Unix seconds, matching the form path, but these tests assert Timestamp.getTime() milliseconds. That either fails against the intended fix or locks in the wrong API contract.

🐛 Proposed test fix
-    `@DisplayName`("JSON body: expires_at must be Unix-millis number, not human-readable")
+    `@DisplayName`("JSON body: expires_at must be Unix-seconds number, not human-readable")
     void jsonBodyEmitsExpiresAtAsUnixMillisNumber() {
         Timestamp expiresAt = Timestamp.from(Instant.parse("2026-06-23T09:54:44Z"));
-        long expectedUnixMillis = expiresAt.getTime();
+        long expectedUnixSeconds = expiresAt.getTime() / 1000L;
...
-        assertEquals(expectedUnixMillis, JsonUtil.getLong(parsed, "expires_at"),
-                "expires_at must be Unix millis (number) in the JSON body");
+        assertEquals(expectedUnixSeconds, JsonUtil.getLong(parsed, "expires_at"),
+                "expires_at must be Unix seconds (number) in the JSON body");
...
         Timestamp expiresAt = Timestamp.from(Instant.now().plus(1, ChronoUnit.DAYS));
-        long expectedUnixMillis = expiresAt.getTime();
+        long expectedUnixSeconds = expiresAt.getTime() / 1000L;
...
-        assertEquals(expectedUnixMillis, JsonUtil.getLong(parsed, "expires_at"));
+        assertEquals(expectedUnixSeconds, JsonUtil.getLong(parsed, "expires_at"));
...
-        assertEquals(expiresAt.getTime(), JsonUtil.getLong(parsed, "expires_at"));
+        assertEquals(expiresAt.getTime() / 1000L, JsonUtil.getLong(parsed, "expires_at"));

Also applies to: 67-80, 102-105

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/chargebee/v4/models/promotionalGrant/params/PromotionalGrantsParamsJsonTest.java`
around lines 36 - 57, The JSON timestamp assertions in
PromotionalGrantsParamsJsonTest are locking in Unix-millis behavior instead of
the intended Unix-seconds contract. Update the expectations in
jsonBodyEmitsExpiresAtAsUnixMillisNumber and the related JSON timestamp tests to
assert numeric Unix seconds rather than Timestamp.getTime() milliseconds, using
the same JSON field checks around PromotionalGrantsParams.toJsonString and
JsonUtil. Keep the test focused on verifying that expiresAt serializes as a
number in seconds for the JSON body.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/java/com/chargebee/v4/models/promotionalGrant/params/PromotionalGrantsParams.java`:
- Around line 93-135: The JSON timestamp contract for PromotionalGrantsParams is
inconsistent: toJsonMap() currently passes expiresAt through as a raw Timestamp,
while the PR expectation and regression should agree on Unix seconds rather than
milliseconds. Update the PromotionalGrantsParams.toJsonMap()/toJsonString path
so expires_at is serialized in the intended unit, and make the associated
regression/test assertion match that same contract using the unique expiresAt
and JsonUtil serialization flow.

In
`@src/main/java/com/chargebee/v4/models/usageEvent/params/UsageEventBatchIngestParams.java`:
- Line 112: Restore Timestamp-compatible APIs in UsageEventBatchIngestParams,
EventsParams, and EventsBuilder by keeping the internal numeric usageTimestamp
representation but adding deprecated Timestamp overloads/accessors for existing
callers. Update the relevant getter and builder methods named getUsageTimestamp
and usageTimestamp(...) to preserve backward compatibility while still
supporting the new wire format.

---

Outside diff comments:
In
`@src/main/java/com/chargebee/v4/models/entitlement/params/EntitlementListParams.java`:
- Around line 160-225: The public nested enum names in EntityTypeIn and
EntityTypeIs have been swapped, which breaks the existing API surface for
consumers compiled against the old symbols. Restore the original enum type names
in EntitlementListParams and keep the wire values unchanged; if the rename is
still needed, add backward-compatible aliases/shims instead of removing the old
nested types. Apply the same compatibility fix in RampListParams so both
parameter classes preserve their published enum symbols for this release.

In
`@src/test/java/com/chargebee/v4/models/promotionalGrant/params/PromotionalGrantsParamsJsonTest.java`:
- Around line 36-57: The JSON timestamp assertions in
PromotionalGrantsParamsJsonTest are locking in Unix-millis behavior instead of
the intended Unix-seconds contract. Update the expectations in
jsonBodyEmitsExpiresAtAsUnixMillisNumber and the related JSON timestamp tests to
assert numeric Unix seconds rather than Timestamp.getTime() milliseconds, using
the same JSON field checks around PromotionalGrantsParams.toJsonString and
JsonUtil. Keep the test focused on verifying that expiresAt serializes as a
number in seconds for the JSON body.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Enterprise

Run ID: ced4388a-0fdb-4bf3-88cf-eaf769d34781

📥 Commits

Reviewing files that changed from the base of the PR and between e8fe429 and 2637ec9.

📒 Files selected for processing (16)
  • CHANGELOG.md
  • src/main/java/com/chargebee/v4/models/entitlement/params/EntitlementListParams.java
  • src/main/java/com/chargebee/v4/models/ledgerOperation/params/LedgerOperationAuthorizeParams.java
  • src/main/java/com/chargebee/v4/models/ledgerOperation/params/LedgerOperationCaptureAuthorizationParams.java
  • src/main/java/com/chargebee/v4/models/ledgerOperation/params/LedgerOperationCaptureParams.java
  • src/main/java/com/chargebee/v4/models/ledgerOperation/params/LedgerOperationReleaseAuthorizationParams.java
  • src/main/java/com/chargebee/v4/models/ledgerOperation/params/ListLedgerOperationsParams.java
  • src/main/java/com/chargebee/v4/models/offerEvent/params/OfferEventsParams.java
  • src/main/java/com/chargebee/v4/models/offerFulfillment/params/OfferFulfillmentsParams.java
  • src/main/java/com/chargebee/v4/models/offerFulfillment/params/OfferFulfillmentsUpdateParams.java
  • src/main/java/com/chargebee/v4/models/personalizedOffer/params/PersonalizedOffersParams.java
  • src/main/java/com/chargebee/v4/models/promotionalGrant/params/PromotionalGrantsParams.java
  • src/main/java/com/chargebee/v4/models/ramp/params/RampListParams.java
  • src/main/java/com/chargebee/v4/models/usageEvent/params/UsageEventBatchIngestParams.java
  • src/main/java/com/chargebee/v4/models/usageEvent/params/UsageEventCreateParams.java
  • src/test/java/com/chargebee/v4/models/promotionalGrant/params/PromotionalGrantsParamsJsonTest.java
✅ Files skipped from review due to trivial changes (1)
  • CHANGELOG.md

@cb-alish cb-alish merged commit f4e7f94 into v4 Jun 29, 2026
8 checks passed
@cb-alish cb-alish deleted the release-v4.11.0 branch June 29, 2026 09:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants